<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>寄生组合式继承</title>
  </head>
  <body>
    <h3>寄生组合式继承</h3>
    <h4>由于要打印原型对象，在浏览器操作比较方便，就用了html文件。</h4>
    <script>
      // 父类
      function Parent(name, age, dataA, dataB) {
        console.warn("Parent 实例化了...");
        // 基本数据类型
        this.name = name;
        this.age = age;
        // 复合数据类型
        this.data = { a: dataA ? dataA : "a", b: dataB ? dataB : "b", c: "c" };

        // 父类内部方法
        this.sayName = function () {
          console.log("我的名字：", this.name);
        };

        // 全局的关键是看这个...原型链的bug在这里
        this.sayData = function () {
          // 这里还不能直接打印对象出来，因为是一个指针，总是指向最新的数据...
          console.log("我的数据如下：");
          console.dir(this.data.a);
          console.dir(this.data.b);
          console.dir(this.data.c);
          console.log("我的数据结束====");
        };
      }

      // 父类原型链方法 (这个跟原型链继承只有半毛钱关系...)
      Parent.prototype.sayAge = function () {
        console.log("我的年龄：", this.age);
      };

      // 子类，不同工种
      function Children(name, age, dataA, dataB, job) {
        // 原型链继承无法通过super 传递给父类，只能通过覆盖的形式了
        Parent.call(this, name, age, dataA, dataB);
        this.job = job;
        this.sayJob = function () {
          console.log("我的工作：", this.job);
        };
      }

      // 这里不使用实例化的父类,不然会调用2次父类的构造函数。
      // Children.prototype = new Parent();
      // 子类已经通过构造函数继承了父类，现在只要继承父类的原型即可。
      // 这边可以寄生式继承的方法，将父类原型绑定到子类即可。
      function childrenFactory(Children, Parent) {
        let prototype = Object.create(Parent.prototype);
        prototype.constructor = Children;
        Children.prototype = prototype;
      }

      childrenFactory(Children, Parent);

      let person1 = new Children(
        "钟先生",
        33,
        "person1A",
        "person1B",
        "程序员"
      );
      // 基本数据类型
      person1.sayName();
      person1.sayAge();
      person1.sayJob();
      // 复合数据类型
      person1.sayData();

      console.log("===person2...");
      let person2 = new Children(
        "刘小姐",
        18,
        "person2A",
        "person2B",
        "清洁阿姨"
      );
      // 基本数据类型
      person2.sayName();
      person2.sayAge();
      person2.sayJob();
      // 复合数据类型
      person2.sayData();

      console.log("===重新打印person1，不用实例化，看看person1会不会被影响...");
      // 基本数据类型
      person1.sayName();
      person1.sayAge();
      person1.sayJob();
      // 复合数据类型
      person1.sayData();
      console.log(
        "===父类构造函数只执行了2次，复合数据类型也不会混乱，很棒..."
      );

    </script>
  </body>
</html>
